package com.timing.finder.framework;

import com.google.gson.JsonObject;
import com.timing.finder.util.json.JsonUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 数据加载定时任务上下文
 *
 * @author JingGe(* ^ ▽ ^ *)
 * @date 2023-03-07 9:49
 * @email 1158055613@qq.com
 */
@Slf4j
public class DataLoadTimingJobContext {
    private final Map<String, Context> contextMap = new ConcurrentHashMap<>();

    public static DataLoadTimingJobContext getInstance() {
        return InstanceHolder.CONTEXT;
    }

    private DataLoadTimingJobContext() {
    }

    void init(String applicationName, Context context) {
        this.contextMap.put(applicationName, context);
    }

    public void update(String applicationName, long currentID, long currentTime, long loaded) {
        Context context = contextMap.get(applicationName);
        if (context == null) {
            return;
        }
        if (currentID > context.currentID.get()) {
            context.currentID.set(currentID);
        } else {
            log.debug("更新ID状态{}相对目前状态{}滞后，不予更新", currentID, context.currentID.get());
        }
        if (currentTime > context.currentTime.get()) {
            context.currentTime.set(currentTime);
        } else {
            log.debug("更新时间状态{}相对目前状态{}滞后，不予更新", currentTime, context.currentTime.get());
        }
        if (loaded > 0) {
            context.loadedCount.addAndGet(loaded);
        }
    }

    public long getCurrentID(String applicationName) {
        if (!contextMap.containsKey(applicationName)) {
            return -1;
        }

        return contextMap.get(applicationName).currentID.get();
    }

    public long getCurrentTime(String applicationName) {
        if (!contextMap.containsKey(applicationName)) {
            return -1;
        }

        return contextMap.get(applicationName).currentTime.get();
    }

    public long getLoadedCount(String applicationName) {
        if (!contextMap.containsKey(applicationName)) {
            return -1;
        }

        return contextMap.get(applicationName).loadedCount.get();
    }

    public void update(String applicationName, long currentID) {
        update(applicationName, currentID, -1);
    }

    public void update(String applicationName, long currentID, long loadedCount) {
        update(applicationName, currentID, System.currentTimeMillis(), loadedCount);
    }

    public void update(String applicationName, String jsonStr) {
        long currentID = -1;
        long currentTime = -1;
        long loaded = -1;
        JsonObject jsonObject = JsonUtil.stringToJsonObj(jsonStr);
        if (jsonObject.has("currentID")) {
            currentID = jsonObject
                    .get("currentID")
                    .getAsLong();
        }
        if (jsonObject.has("currentTime")) {
            currentTime = jsonObject
                    .get("currentTime")
                    .getAsLong();
        }
        if (jsonObject.has("loadedCount")) {
            loaded = jsonObject
                    .get("loadedCount")
                    .getAsLong();
        }
        update(applicationName, currentID, currentTime, loaded);
    }

    public String toJSON(String applicationName) {
        if (!contextMap.containsKey(applicationName)) {
            return null;
        }
        return JsonUtil.pojoToJsonString(contextMap.get(applicationName));
    }

    static class InstanceHolder {
        private static final DataLoadTimingJobContext CONTEXT = new DataLoadTimingJobContext();
    }

    static class Context {
        AtomicLong currentID = new AtomicLong(0);
        AtomicLong currentTime = new AtomicLong(System.currentTimeMillis());
        AtomicLong loadedCount = new AtomicLong(0L);

        public Context(long currentID, long currentTime, long loadedCount) {
            this.currentID.set(currentID);
            this.currentTime.set(currentTime);
            this.loadedCount.set(loadedCount);
        }

        public Context() {
        }
    }
}
